home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-17 | 6.3 KB | 257 lines | [TEXT/CWIE] |
- /********************************************************************************/
- //
- // Folder Searching Routines
- //
- // Based on code supplied by Andrew Duncan
- //
- // Version 1.0.1
- //
- // Created: 13 May 1996
- // Modified: 17 June 1996
- //
- /********************************************************************************/
-
- #include "Main.h"
- #include "DoStuff.h"
- #include "SearchFolder.h"
- #include "DialogUtil.h"
- #include "Utility.h"
-
- // kTimeOut defines how much time (in ticks) the program is willing to wait for
- // other programs to get events while it's stepping though the folders/files.
- // To make the program more multifinder-friendly, make the number bigger. The
- // downside to this is that the program slows down, especially while in the
- // background.
- // To speed things up, make the number smaller. This will slow down background
- // applications. If you go too far, they will become sluggish, and when you
- // switch to, say, the Finder while the program is working, you will become
- // frustrated at how long you have to wait for your clicks to register and
- // whatnot.
- #define kTimeOut 3
-
-
- // Globals
-
- static short sInputVRefNum;
-
-
- // Prototypes
-
- Boolean FSSpecToDirID( FSSpec dirSpec, long* dirID );
- static OSErr ReadDir( long dirID, short dirIndex,
- FSSpec* theSpec, Boolean* isDirectory, long* itsDirID );
- Boolean RecursiveReadDir( long dirID );
- Boolean WorkingEvent( EventRecord event );
- Boolean WorkingMenu( long menuChoice );
-
-
- //
- // DoAllFiles
- //
- void DoAllFiles( FSSpec startSpec )
- {
- long dirID;
-
- if ( FSSpecToDirID( startSpec, &dirID ) )
- RecursiveReadDir( dirID );
- else
- DisplayAlert( "\pERROR: Problem processing selected folder name" );
- }
-
-
- //
- // FSSpecToDirID
- //
- // Takes the FSSpec of a directory and returns a DirID to it.
- // Works by creating a FSSpec for a (probably) non-existant file in that
- // directory named "?" and grabbing the ParID field of the new FSSpec.
- // Returns True if successful in getting the directory ID, false otherwise.
- //
-
- // Andy sez:
- // Should change to just use the ioDrDirID returned by PBGetCatInfo!!!
-
- Boolean FSSpecToDirID( FSSpec dirSpec, long* dirID )
- {
- FSSpec newSpec;
- OSErr err;
- char nameLength, i;
-
- sInputVRefNum = dirSpec.vRefNum;
-
- if ( IsAFolder( &dirSpec ) )
- {
- nameLength = dirSpec.name[0]; // Get the length of directory name
-
- // Shift the name one character to the right:
- i = nameLength + 1;
- while ( i > 1 )
- {
- dirSpec.name[i] = dirSpec.name[i - 1];
- i--;
- }
-
- dirSpec.name[1] = ':'; // Make it a partial pathname
- dirSpec.name[nameLength + 2] = ':'; // Append a colon
- dirSpec.name[nameLength + 3] = '?'; // An unlikely filename
- dirSpec.name[0] += 3; // Fix the length byte for additions
-
- // Make an FSSpec for the new filename and get the parent ID from it:
- err = FSMakeFSSpec( dirSpec.vRefNum, dirSpec.parID, dirSpec.name, &newSpec );
-
- if ( ( err == noErr ) || ( err == fnfErr ) )
- {
- *dirID = newSpec.parID;
- return ( true );
- }
- else
- return ( false );
- }
- else
- return ( false );
- }
-
-
- //
- // ReadDir
- //
- static OSErr ReadDir( long dirID, short dirIndex, // Input
- FSSpec* theSpec, Boolean* isDirectory, long* itsDirID ) // Output
- {
- CInfoPBRec pb;
- OSErr err;
-
- pb.hFileInfo.ioCompletion = (IOCompletionUPP) NULL;
- pb.hFileInfo.ioNamePtr = theSpec->name;
- pb.hFileInfo.ioVRefNum = sInputVRefNum; // DANGER! NEVER SET!
- pb.hFileInfo.ioFDirIndex = dirIndex; // Find out about nth file
- pb.hFileInfo.ioDirID = dirID;
-
- err = PBGetCatInfo( &pb, false );
- if ( err == noErr )
- {
- err = FSMakeFSSpec(sInputVRefNum, dirID, pb.hFileInfo.ioNamePtr, theSpec);
- *isDirectory = pb.hFileInfo.ioFlAttrib & (1 << 4);
- if (*isDirectory) *itsDirID = pb.dirInfo.ioDrDirID;
- return noErr;
- }
- else
- return err;
- }
-
-
- //
- // RecursiveReadDir
- // This is the routine which recurses folder to folder, handing off file/folder
- // info to the routines in DoStuff.c
- // The routine returns true when it has finished the folder it is doing normally,
- // false when it is aborted.
- //
- Boolean RecursiveReadDir( long dirID )
- {
- FSSpec theSpec;
- OSErr err = noErr;
- short dirIndex = 1; // What item in the dir to look at - start with 1
- Boolean isDirectory;
- long itsDirID;
- EventRecord event;
-
- while ( err == noErr )
- {
- BusyCursor(); // Set the cursor to the watch to show we're doing something.
-
- // Be a good citizen and let other applications get some processor time,
- // also check for command-period (abort) at the same time:
- if ( WaitNextEvent( keyDownMask + mDownMask, &event, kTimeOut, nil ) )
- {
- if ( !( WorkingEvent( event ) ) )
- return( false );
- }
-
- err = ReadDir( dirID, dirIndex, &theSpec, &isDirectory, &itsDirID );
- if ( err == noErr )
- {
-
- if ( isDirectory )
- {
- if ( !( RecursiveReadDir( itsDirID ) ) ) // Recurse into the directory
- {
- SetCursor(&(qd.arrow)); // Set the cursor back to the arrow.
- return ( false ); // Abort.
- }
- DoToEachFolder( theSpec );
- }
- else
- DoToEachFile( theSpec );
-
- dirIndex++; // Move on to the next item
- }
- }
- return ( true );
- }
-
-
- //
- // WorkingEvent
- // A little mini event handler to detect if the user wants to abort while the
- // program is working.
- //
- Boolean WorkingEvent( EventRecord event )
- {
- WindowPtr window;
- long menuChoice;
- char theChar;
- short thePart;
-
- switch ( event.what )
- {
- case mouseDown:
- thePart = FindWindow( event.where, & window );
-
- switch ( thePart )
- {
- case inMenuBar:
- menuChoice = MenuSelect( event.where );
- if ( !( WorkingMenu( menuChoice ) ) )
- return ( false );
- break;
- case inSysWindow:
- SystemClick( &event, window );
- break;
- }
- break;
-
- case keyDown:
- case autoKey:
- if ( event.modifiers & cmdKey ) // Is the command key pressed?
- {
- theChar = event.message & charCodeMask;
- menuChoice = MenuKey( theChar );
- if ( !( WorkingMenu( menuChoice ) ) )
- return ( false );
- }
- break;
- }
- return( true );
- }
-
-
- //
- // WorkingMenu
- // A little mini menu handler to detect if the user wants to abort while the
- // program is working.
- //
- Boolean WorkingMenu( long menuChoice )
- {
- short menu, item;
-
- menu = HiWord( menuChoice );
- item = LoWord( menuChoice );
- if ( ( menu == mFile ) && ( item == iOpen ) ) // The Abort item.
- return( false );
- else
- {
- HandleMenuChoice( menuChoice ); // Let the main menu procedure deal with it
- return( true ); // Keep on working
- }
- }